package com.code.services.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.code.exceptions.WalletException;
import com.code.managers.HttpManager;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 请求钱包服务
 *
 * @author xiaoyaowang
 */
@Service
@Slf4j
public class RequestWalletService {

    @Resource
    private HttpManager httpManager;

    @Value("${wallet.transfer.accountName}")
    private String accountName;

    @Value("${wallet.transfer.secondAmount}")
    private String secondAmount;

    @Value("${wallet.transfer.thirdAmount}")
    private Integer thirdAmount;

    @Value("${wallet.transfer.tpErc20Addr}")
    private String tpErc20Addr;

    @Value("${wallet.transfer.tpAddr}")
    private String tpAddr;

    @Value("${wallet.transfer.memo}")
    private String memo;

    @Value("${wallet.transfer.precision}")
    private Integer precision;

    /**
     * 打开钱包
     *
     * @return 打开钱包与否
     */
    public Boolean openWallet() {
        List<Object> params = new ArrayList<>();
        // 下面固定死
        params.add("tp-airdrop1023.");
        String body = httpManager.sendRpcReq("unlock", params);
        if (!StringUtils.isBlank(body)) {
            JSONObject resultJson = JSON.parseObject(body);
            if (resultJson.containsKey("error")) {
                JSONObject errorJson = resultJson.getJSONObject("error");
                if (null != errorJson) {
                    log.error("请求钱包异常返回数据:{}", errorJson);
                    throw new WalletException(errorJson.toJSONString());
                }
            }
        } else {
            return false;
        }
        return true;
    }

    /**
     * 获取余额
     *
     * @return 余额
     */
    public String getBalance() {
        List<Object> params = new ArrayList<>();
        // 下面固定死
        params.add(accountName);
        params.add(tpErc20Addr);
        params.add("balanceOf");
        params.add(tpAddr);
        String body = httpManager.sendRpcReq("invoke_contract_offline", params);
        if (!StringUtils.isBlank(body)) {
            JSONObject resultJson = JSON.parseObject(body);
            if (null != resultJson && resultJson.containsKey("result")) {
                String balance = resultJson.getString("result");
                if (StringUtils.isBlank(balance)) {
                    return "0";
                }
                return new BigDecimal(balance).divide(new BigDecimal("100000000")).setScale(precision, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();
            } else {
                return "0";
            }
        } else {
            return "0";
        }
    }

    /**
     * 获取XWC余额
     *
     * @return 余额
     */
    public String getXwcBalance() {
        List<Object> params = new ArrayList<>();
        // 下面固定死
        params.add(tpAddr);
        String body = httpManager.sendRpcReq("get_addr_balances", params);
        if (!StringUtils.isBlank(body)) {
            JSONObject resultJson = JSON.parseObject(body);
            if (null != resultJson && resultJson.containsKey("result")) {
                String result = resultJson.getString("result");
                if (StringUtils.isBlank(result)) {
                    return "0";
                }
                JSONArray xwcAssets = JSON.parseArray(result);
                if (CollectionUtils.isEmpty(xwcAssets)) {
                    return "0";
                }
                JSONObject xwcJson = (JSONObject) xwcAssets.get(0);
                String xwcBalance = "0";
                if (null != xwcJson && xwcJson.containsKey("amount")) {
                    xwcBalance = xwcJson.getString("amount");
                    if (StringUtils.isBlank(xwcBalance)) {
                        return "0";
                    }
                }
                return new BigDecimal(xwcBalance).divide(new BigDecimal("100000000")).setScale(precision, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();
            } else {
                return "0";
            }
        } else {
            return "0";
        }
    }

    /**
     * 向审核通过的地址转账
     *
     * @return 打开钱包与否
     */
    public Boolean transferToAddr(String walletAddr, String amount) {
        List<Object> params = new ArrayList<>();
        // 下面固定死
        params.add(accountName);
        params.add(new BigDecimal(secondAmount).setScale(precision, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString());
        params.add(thirdAmount);
        params.add(tpErc20Addr);
        params.add("transfer");
        StringBuilder sb = new StringBuilder(1 << 3);
        sb.append(walletAddr);
        sb.append(",");
        sb.append(new BigDecimal(amount).multiply(new BigDecimal("100000000")).setScale(precision, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString());
        sb.append(",");
        sb.append(memo);
        params.add(sb.toString());
        String body = httpManager.sendRpcReq("invoke_contract", params);
        if (!StringUtils.isBlank(body)) {
            JSONObject resultJson = JSON.parseObject(body);
            if (resultJson.containsKey("error")) {
                JSONObject errorJson = resultJson.getJSONObject("error");
                if (null != errorJson) {
                    log.error("请求钱包异常返回数据:{}", errorJson);
                    throw new WalletException(errorJson.toJSONString());
                }
            }
        } else {
            return false;
        }
        return true;
    }

    /**
     * 关闭钱包
     *
     * @return 关闭钱包与否
     */
    public Boolean closeWallet() {
        List<Object> params = new ArrayList<>();
        // 下面固定死
        String body = httpManager.sendRpcReq("lock", params);
        if (!StringUtils.isBlank(body)) {
            JSONObject resultJson = JSON.parseObject(body);
            if (resultJson.containsKey("error")) {
                JSONObject errorJson = resultJson.getJSONObject("error");
                if (null != errorJson) {
                    log.error("请求钱包异常返回数据:{}", errorJson);
                    throw new WalletException(errorJson.toJSONString());
                }
            }
        } else {
            return false;
        }
        return true;
    }

    /**
     * 转账
     *
     * @param walletAddr 钱包地址
     * @param amount     金额
     */
    public void transferAmountToAddr(String walletAddr, String amount) {
        // 第一步：打开钱包
        boolean openWallet = openWallet();
        // 第二步：向审核成功的地址转账
        boolean transfer = false;
        if (openWallet) {
            transfer = transferToAddr(walletAddr, amount);
        }
        // 第三步：关闭钱包
        if (transfer) {
            closeWallet();
        }
    }

}
